--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Commit 1e440c569ae0f7dcff3ebf81524ce305aab14436
Parents : 473c8e6
Author : Ivan <ivan@quad4.io>
Signature : Invalid signer <e46112d44649266d71fe2193e00a4710>, author is <ivan@quad4.io>
Date : 2026-07-08T10:03:17-05:00
fix(rrc/manager): clean up room data on removal by discarding messages, unread counts, mentions, and members
Changes
2 files changed, 80 insertions(+), 0 deletions(-)
Diff
diff --git a/meshchatx/src/backend/rrc/manager.py b/meshchatx/src/backend/rrc/manager.py
index 08a3a259..9da3a098 100644
--- a/meshchatx/src/backend/rrc/manager.py
+++ b/meshchatx/src/backend/rrc/manager.py
@@ -630,6 +630,12 @@ class RRCHub:
self._send_env(env)
with self._lock:
self.rooms.discard(room_n)
+ self.messages.pop(room_n, None)
+ self.unread_rooms.discard(room_n)
+ self.unread_counts.pop(room_n, None)
+ self.mention_rooms.discard(room_n)
+ self.members.pop(room_n, None)
+ self._delete_history(room_n)
self.manager.save()
self.manager._notify_change(self)
diff --git a/tests/backend/test_rrc_part_room.py b/tests/backend/test_rrc_part_room.py
new file mode 100644
index 00000000..60cdefc6
--- /dev/null
+++ b/tests/backend/test_rrc_part_room.py
@@ -0,0 +1,74 @@
+# SPDX-License-Identifier: 0BSD
+
+"""Regression test: leaving a connected RRC room must drop it from the
+known-rooms list.
+
+`RRCHub.ordered_known_rooms()` treats any room with an entry in
+`self.messages` as "known", even if it was never joined. `part_room()`
+(used for a connected hub) previously only discarded the room from
+`self.rooms`, leaving its `messages` entry (and unread/member state)
+behind, so the room kept reappearing in the sidebar after leaving it.
+"""
+
+from meshchatx.src.backend.rrc.manager import RRCHub
+
+
+class FakeIdentity:
+ def __init__(self, hash_bytes):
+ self.hash = hash_bytes
+
+
+class FakeManager:
+ def __init__(self):
+ self.changes = 0
+ self.identity = FakeIdentity(b"\x11" * 16)
+
+ def _notify_change(self, hub=None):
+ self.changes += 1
+
+ def save(self):
+ pass
+
+ def _history_path(self, hub, room):
+ return ""
+
+ def _ensure_history_dir(self, hub):
+ pass
+
+
+HUB_HASH = bytes(range(16))
+
+
+def make_hub():
+ return RRCHub(FakeManager(), HUB_HASH, name="Hub")
+
+
+def test_part_room_removes_room_from_known_rooms():
+ hub = make_hub()
+ hub.status = RRCHub.STATUS_CONNECTED
+ hub.rooms.add("lobby")
+ hub.messages["lobby"] = []
+ hub.unread_rooms.add("lobby")
+ hub.unread_counts["lobby"] = 3
+ hub.members["lobby"] = {b"\x01" * 16}
+
+ assert "lobby" in hub.ordered_known_rooms()
+
+ hub.part_room("lobby")
+
+ assert "lobby" not in hub.ordered_known_rooms()
+ assert "lobby" not in hub.messages
+ assert "lobby" not in hub.unread_rooms
+ assert "lobby" not in hub.unread_counts
+ assert "lobby" not in hub.members
+
+
+def test_part_room_notifies_manager_of_change():
+ hub = make_hub()
+ hub.status = RRCHub.STATUS_CONNECTED
+ hub.rooms.add("general")
+ hub.messages["general"] = []
+
+ hub.part_room("general")
+
+ assert hub.manager.changes >= 1
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────